package com.hopechart.micro.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.serializer.PropertyFilter;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.hopechart.micro.common.constant.Constant;
import com.hopechart.micro.common.constant.Response;
import org.apache.commons.lang.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author daijiang
 */
public class JsonUtil {

    public static SerializerFeature[] features = {
            SerializerFeature.WriteNullStringAsEmpty,
            SerializerFeature.WriteNullListAsEmpty,
            SerializerFeature.WriteNullNumberAsZero,
            SerializerFeature.WriteNullBooleanAsFalse,
            SerializerFeature.WriteDateUseDateFormat,
            SerializerFeature.DisableCircularReferenceDetect};

    public static String resultSuccess(Integer code, String msg, Object data) {
        return toString(new Response(code, msg, data));
    }

    public static String resultSuccess(Integer code, String msg) {
        return toString(new Response(code, msg, null));
    }

    public static String resultError(Integer code, String error, Object data) {
        return toString(new Response(code, error, data));
    }

    public static String resultList(Integer code, String msg, Integer pageNo, Integer pageSize, Object data) {
        Map<String, Object> rs = new HashMap<String, Object>();
        rs.put("code", code);
        rs.put("message", StringUtils.isEmpty(msg) ? Constant.DEFAULT_MESSAGE : msg);
        rs.put("data", null == data ? new Object() : data);
        rs.put("pageNo", pageNo == null ? Constant.DEFAULT_PAGE : pageNo);
        rs.put("pageSize", pageSize == null ? Constant.DEFAULT_PAGE_ROWS : pageSize);
        return toString(rs);
    }

    public static String resultFeatures(Integer code, String msg, Object data, SerializerFeature... feature) {
        return JSON.toJSONString(new Response(code, msg, data), feature);
    }

    public static String resultDate(Integer code, String msg, Object data, String dateFormat) {
        return JSON.toJSONStringWithDateFormat(new Response(code, msg, data), dateFormat, features);
    }

    public static String resultIncludes(Integer code, String msg, Object data, String... properties) {
        return toStringIncludes(new Response(code, msg, data), properties);
    }

    public static String resultExcludes(Integer code, String msg, Object data, Class<?> type, String... properties) {
        return toStringExcludes(new Response(code, msg, data), type, properties);
    }

    public static String toString(Object data) {
        return JSON.toJSONString(data, features);
    }

    private static String toStringIncludes(Object data, final String... properties) {
        PropertyFilter filter = new PropertyFilter() {
            @Override
            public boolean apply(Object source, String name, Object value) {
                if (source.getClass() == HashMap.class && ("code".equals(name) || "data".equals(name) || "msg".equals(name))) {
                    return true;
                }
                for (String pro : properties) {
                    if (pro.equals(name)) {
                        return true;
                    }
                }
                return false;
            }
        };
        return JSON.toJSONString(data, filter, features);
    }

    private static String toStringExcludes(Object data, final Class<?> type, final String... properties) {
        PropertyFilter filter = new PropertyFilter() {
            @Override
            public boolean apply(Object source, String name, Object value) {
                if (source.getClass() == type) {
                    for (String pro : properties) {
                        if (pro.equals(name)) {
                            return false;
                        }
                    }
                }
                return true;
            }
        };
        return JSON.toJSONString(data, filter, features);
    }

    public static <T> List<T> parseObjects(String jsonObjects, Class<T> clazz) throws RuntimeException {
        try {
            return JSONArray.parseArray(jsonObjects, clazz);
        } catch (Exception e) {
            throw new RuntimeException("JSON数据解析异常", e);
        }
    }
}
